package phong.musicplayer;

import java.io.IOException;

import android.app.Notification;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnSeekCompleteListener;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;
import android.support.v4.content.LocalBroadcastManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.widget.Toast;

public class PlayService extends Service implements OnCompletionListener,
		OnPreparedListener, OnErrorListener, OnSeekCompleteListener,
		OnInfoListener, OnBufferingUpdateListener {

	// https://dl.dropboxusercontent.com/u/182179436/Tre_AnhYeuNguoiKhacRoi-KhacViet.mp3
	// https://dl.dropboxusercontent.com/u/182179436/Tre_BucTranhTuNuocMat-MrSiro.mp3
	// https://dl.dropboxusercontent.com/u/182179436/Tre_ConMuaNgangQua-MTP.mp3
	// https://dl.dropboxusercontent.com/u/182179436/Tre_KhiNguoiLonCoDon-HongPhuoc.mp3
	// https://dl.dropboxusercontent.com/u/182179436/Tre_MayVaNui-TheBells.mp3
	// https://dl.dropboxusercontent.com/u/182179436/Tre_NangAmXaDan-SonTung-MTP.mp3
	// https://dl.dropboxusercontent.com/u/182179436/Tre_NguoiYeuCu-KhoiMy.mp3
	// https://dl.dropboxusercontent.com/u/182179436/Tre_SaiLamVanLaAnh-TheMen.mp3
	// https://dl.dropboxusercontent.com/u/182179436/Tre_ThuCuoi-YanBiftMrTftHangBingBong.mp3
	// https://dl.dropboxusercontent.com/u/182179436/Tre_TinhYeuMauNang-DoanThuyTrangftBigDaddy.mp3

	// http://mp3.zing.vn/bai-hat/Nhac-Chuong-Hay-Nhac-Chuong-Hay/IW8F7IFB.html
	// http://mp3.zing.vn/bai-hat/Nhac-Chuong-hai-Nhac-Chuong/IW8ICE9E.html

	MediaPlayer mediaPlayer = new MediaPlayer();
	String sentAudioLink;
	static final int NOTIFICATION_ID = 1;

	LocalBroadcastManager broadcaster;
	static final String PLAY_COMPLETED = "phong.musicplayer.PLAY_COMPLETED";
	static final String PLAYING = "phong.musicplayer.PLAYING";

	boolean isPauseInCall = false;
	PhoneStateListener phoneStateListener;
	TelephonyManager telephonyManager;

	static final String BROADCAST_BUFFER = "phong.musicplayer.broadcastbuffer";
	Intent bufferIntent;

	Intent seekIntent;
	String strSeekPos;
	int intSeekPos, mediaPos, mediaMax;
	final Handler handler = new Handler();
	static final String BROADCAST_SEEK = "phong.musicplayer.seekprogress";

	@Override
	public void onCreate() {
		bufferIntent = new Intent(BROADCAST_BUFFER);

		seekIntent = new Intent(BROADCAST_SEEK);
		mediaPlayer.setOnSeekCompleteListener(this);

		mediaPlayer.setOnCompletionListener(this);
		mediaPlayer.setOnErrorListener(this);
		mediaPlayer.setOnPreparedListener(this);
		mediaPlayer.setOnBufferingUpdateListener(this);

		mediaPlayer.setOnInfoListener(this);
		// mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
		mediaPlayer.reset();

		broadcaster = LocalBroadcastManager.getInstance(this);
	}

	public void sendResult(String message) {
		Intent intent = new Intent(message);
		if (message != null)
			intent.putExtra(message, message);
		broadcaster.sendBroadcast(intent);
	}

	// ----------------Broadcast buffer intent---------------------------
	void sendBufferingBroadcast() {
		bufferIntent.putExtra("buffering", "1");// 1 : buffering
		sendBroadcast(bufferIntent);
	}

	void sendBufferCompleteBroadcast() {
		bufferIntent.putExtra("buffering", "0"); // 0 : buffer complete
		sendBroadcast(bufferIntent);
	}

	void exitBufferDialogWhenLinkError() {
		bufferIntent.putExtra("buffering", "-1");
		sendBroadcast(bufferIntent);
	}

	// --------------End code broadcast buffer intent--------------------------

	// ---------------SeekBar Handler----------------------------------------
	void setupSeekHandler() {
		handler.removeCallbacks(sendUpdateToUI);
		handler.postDelayed(sendUpdateToUI, 1000); // 1 second
	}

	Runnable sendUpdateToUI = new Runnable() {
		@Override
		public void run() {
			LogMediaPosition();
			handler.postDelayed(this, 1000); // 1 second
		}
	};

	void LogMediaPosition() {
		if (mediaPlayer.isPlaying()) {
			mediaPos = mediaPlayer.getCurrentPosition();
			mediaMax = mediaPlayer.getDuration();
			seekIntent.putExtra("counter", String.valueOf(mediaPos));
			seekIntent.putExtra("media_max", String.valueOf(mediaMax));
			sendBroadcast(seekIntent);
		}
	}

	// Receive seek position if changed by user in Activity
	BroadcastReceiver seekBroadcastReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			updateSeekPos(intent);
		}
	};

	// Update seek position to Activity
	void updateSeekPos(Intent seekIntent) {
		int seekPos = seekIntent.getIntExtra("seekpos", 0);
		if (mediaPlayer.isPlaying()) {
			handler.removeCallbacks(sendUpdateToUI);
			mediaPlayer.seekTo(seekPos);
			setupSeekHandler();
		}
	}

	// ---------------End code SeekBar---------------------------------------

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		phoneStateListener = new PhoneStateListener() {
			@Override
			public void onCallStateChanged(int state, String incomingNumber) {
				super.onCallStateChanged(state, incomingNumber);

				// ---------Set up receiver for seekbar change------------
				registerReceiver(seekBroadcastReceiver, new IntentFilter(
						MainActivity.BROADCAST_SEEKBAR));

				switch (state) {
				case TelephonyManager.CALL_STATE_OFFHOOK:
				case TelephonyManager.CALL_STATE_RINGING:
					if (mediaPlayer != null) {
						pause();
						isPauseInCall = true;
					}
					break;
				case TelephonyManager.CALL_STATE_IDLE:
					if (mediaPlayer != null) {
						if (isPauseInCall) {
							isPauseInCall = false;
							playMedia();
						}
					}
					break;
				}
			}
		};
		telephonyManager.listen(phoneStateListener,
				PhoneStateListener.LISTEN_CALL_STATE);

		initNotification();

		sentAudioLink = intent.getExtras().getString("sentAudioLink");
		mediaPlayer.reset();
		if (!mediaPlayer.isPlaying()) {
			try {
				mediaPlayer.setDataSource(sentAudioLink);
				sendBufferingBroadcast();// buffering when start playing
				mediaPlayer.prepareAsync();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		// Set up seekbar handler
		setupSeekHandler();

		return START_STICKY;
	}

	@Override
	public void onPrepared(MediaPlayer arg0) {
		sendBufferCompleteBroadcast();// buffer complete & ready play music
		playMedia();
	}

	@Override
	public void onCompletion(MediaPlayer arg0) {
		stopMedia();
		stopSelf(); // stop Play Service
		cancelNotification();
		MainActivity.song_running_time.setText("00:00:00");
		sendResult(PLAY_COMPLETED);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (mediaPlayer != null) {
			if (mediaPlayer.isPlaying()) {
				mediaPlayer.stop();
			}
			mediaPlayer.release();
		}
		if (phoneStateListener != null) {
			telephonyManager.listen(phoneStateListener,
					PhoneStateListener.LISTEN_NONE);
		}

		cancelNotification();

		// Unregister seekbar receiver
		unregisterReceiver(seekBroadcastReceiver);

		// Stop the seekbar handler from sending updates to UI
		handler.removeCallbacks(sendUpdateToUI);
	}

	@Override
	public void onSeekComplete(MediaPlayer mp) {
		if (!mediaPlayer.isPlaying()) {
			playMedia();
		}
	}

	@Override
	public boolean onError(MediaPlayer mp, int what, int extra) {
		switch (what) {
		case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
			Toast.makeText(this,
					"MEDIA ERROR NOT VALID FOR PROGRESSIVE PLAYBACK " + extra,
					Toast.LENGTH_SHORT).show();
			exitBufferDialogWhenLinkError();
			break;
		case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
			Toast.makeText(this, "MEDIA ERROR SERVER DIED " + extra,
					Toast.LENGTH_SHORT).show();
			exitBufferDialogWhenLinkError();
			break;
		case MediaPlayer.MEDIA_ERROR_UNKNOWN:
			Toast.makeText(this, "MEDIA ERROR UNKNOWN " + extra,
					Toast.LENGTH_SHORT).show();
			exitBufferDialogWhenLinkError();
			break;
		default:
			break;
		}
		return false;
	}

	@Override
	public void onBufferingUpdate(MediaPlayer mp, int percent) {

	}

	@Override
	public boolean onInfo(MediaPlayer arg0, int arg1, int arg2) {
		return false;
	}

	void playMedia() {
		mediaPlayer.start();

		sendResult(PLAYING);
	}

	void stopMedia() {
		if (mediaPlayer.isPlaying()) {
			mediaPlayer.stop();
		}
	}

	public void pause() {
		if (mediaPlayer.isPlaying()) {
			mediaPlayer.pause();
		}
	}

	public void resume() {
		if (!mediaPlayer.isPlaying()) {
			mediaPlayer.start();
		}
	}

	void initNotification() {
		Intent notificationIntent = new Intent(this, MainActivity.class);
		PendingIntent contentIntent = PendingIntent.getActivity(
				getApplicationContext(), 0, notificationIntent, 0);

		CharSequence tickerText = "MusicPlayer";
		CharSequence contentTitle = "Music In Service";
		CharSequence contentText = "Listen To Music While Performing Other Tasks";
		Resources res = getResources();
		NotificationCompat.Builder builder = new Builder(
				getApplicationContext());
		builder.setContentIntent(contentIntent)
				.setSmallIcon(R.drawable.small_icon)
				.setLargeIcon(
						BitmapFactory
								.decodeResource(res, R.drawable.large_icon))
				.setTicker(tickerText).setWhen(System.currentTimeMillis())
				.setContentTitle(contentTitle).setContentText(contentText)
				.setAutoCancel(true);
		Notification notification = builder.build();

		String notificationService = Context.NOTIFICATION_SERVICE;
		NotificationManager notificationManager = (NotificationManager) getSystemService(notificationService);
		notificationManager.notify(NOTIFICATION_ID, notification);
	}

	void cancelNotification() {
		String notificationService = Context.NOTIFICATION_SERVICE;
		NotificationManager notificationManager = (NotificationManager) getSystemService(notificationService);
		notificationManager.cancel(NOTIFICATION_ID);
	}

	// @Override
	// public IBinder onBind(Intent arg0) {
	// return null;
	// }

	public class ServiceBinder extends Binder {
		public PlayService getService() {
			return PlayService.this;
		}
	}

	ServiceBinder binder = new ServiceBinder();

	@Override
	public IBinder onBind(Intent intent) {
		return binder;
	}
}
